/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package fr.insta.browser.container;

import fr.insta.browser.service.history.HistoryService;
import fr.insta.browser.service.history.HistorySingleTabServiceFactory;
import fr.insta.browser.service.history.IHistoryService;
import fr.insta.browser.service.tab.ITabService;
import fr.insta.browser.service.tab.TabService;
import fr.insta.browser.view.frame.MainFrame;
import fr.insta.browser.view.tab.ITabFactory;
import fr.insta.browser.view.tab.TabFactory;
import fr.insta.browser.view.webview.WebViewFactory;

/**
 * Container de l'application
 * Permet de récuperer tout les services partagé de l'application
 *
 * @author Maarek
 * @version $Id: $Id
 */
public class Container {

    // <editor-fold defaultstate="collapsed" desc="Utils">
    /**
     * Permet de créer facilement un service
     *
     * @param <T> Le type du service retourné par la callback
     * @param callback La callback de création du service. Renvoi un service de
     * type T, et prend le container en paramètre
     * @return Renvoi une callback qui permet de créer un service lors de son
     * premiere appel seulement.
     */
    public <T> F<T> share(final FC<T> callback) {
        return new Share(this, callback);
    }

    private interface FC<T> extends F1<T, Container> {
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="MainFrame">
    protected F<MainFrame> shareMainFrame = this.share(new FC<MainFrame>() {
        @Override
        public MainFrame call(Container c) {
        	MainFrame frame = new MainFrame(c.getTabFactory(), c.getTabService(), c.getHistoryService());
            frame.init();
            return frame;
        }
    });

    /**
     * Recupère la fenêtre principal de l'application
     *
     * @return a {@link fr.insta.browser.view.frame.MainFrame} object.
     */
    public MainFrame getMainFrame() {
        return shareMainFrame.call();
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Factory">
    protected F<WebViewFactory> shareWebViewFactory = this.share(new FC<WebViewFactory>() {
        @Override
        public WebViewFactory call(Container c) {
            return new WebViewFactory();
        }
    });

    /**
     * Recupère le WebViewFactory partagé de l'application
     *
     * @return a {@link fr.insta.browser.view.webview.WebViewFactory} object.
     */
    public WebViewFactory getWebViewFactory() {
        return shareWebViewFactory.call();
    }

    protected F<ITabFactory> shareTabFactory = this.share(new FC<ITabFactory>() {
        @Override
        public ITabFactory call(Container c) {
            return new TabFactory(c.getWebViewFactory(), c.getTabService(), c.getHistoryService());
        }
    });

    /**
     * Recupère le ITabFactory partagé de l'application
     *
     * @return a {@link fr.insta.browser.view.tab.ITabFactory} object.
     */
    public ITabFactory getTabFactory() {
        return shareTabFactory.call();
    }

    protected F<HistorySingleTabServiceFactory> shareHistorySingleTabServiceFactory = this.share(new FC<HistorySingleTabServiceFactory>() {
        @Override
        public HistorySingleTabServiceFactory call(Container c) {
            return new HistorySingleTabServiceFactory();
        }
    });

    /**
     * Recupère le HistorySingleTabServiceFactory de l'application
     *
     * @return a {@link fr.insta.browser.service.history.HistorySingleTabServiceFactory} object.
     */
    public HistorySingleTabServiceFactory getHistorySingleTabServiceFactory() {
        return shareHistorySingleTabServiceFactory.call();
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Service">
    protected F<ITabService> shareTabService = this.share(new FC<ITabService>() {
        @Override
        public ITabService call(Container c) {
            return new TabService(c.getHistorySingleTabServiceFactory());
        }
    });

    /**
     * Recupère le service de tab
     *
     * @return a {@link fr.insta.browser.service.tab.ITabService} object.
     */
    public ITabService getTabService() {
        return shareTabService.call();
    }

    protected F<IHistoryService> shareHistoryService = this.share(new FC<IHistoryService>() {

        @Override
        public IHistoryService call(Container c) {
            return new HistoryService();
        }

    });

    /**
     * Récupère le service d'historique
     *
     * @return a {@link fr.insta.browser.service.history.IHistoryService} object.
     */
    protected IHistoryService getHistoryService() {
        return shareHistoryService.call();
    }
    // </editor-fold>
}
